﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.Remoting;

namespace Interfaces
{
    public interface IPeer
    {
        string Name { get; set; }

        /// <summary>
        /// Método para pesquisa de assuntos.
        /// igual ao get de KnownArticles?!?!?
        /// </summary>
        /// <returns></returns>
        IEnumerable GetArticles();

        /// <summary>
        /// Método para pedir, ao SuperPeer, Peers que possuam artigos com o assunto indicado.
        /// </summary>
        /// <param name="subject"></param>
        /// <returns>Retorna os Peers que o SuperPeer tem que conheçam o assunto indicado no parâmetro.</returns>
        IDictionary<string, IPeer> GetPeersFor(string subject);

        /// <summary>
        /// Método de callback passado aquando do BeginInvoke executado no método GetPeersAsync.
        /// Regista um conjunto de Peers que possuam artigos com assunto correspondente ao deste Peer.
        /// </summary>
        /// <param name="ar"></param>
        void CallbackRegisterPeersFor(IAsyncResult ar);

        /// <summary>
        /// Promove-se a SuperPeer
        /// </summary>
        /// <exception cref="RemotingException">Caso não consiga obter ligação com o SuperPeer.</exception>
        void PromoteToSuperPeer();

        /// <summary>
        /// Serve para registar superPeer como SuperPeer deste Peer e para registar este Peer com Peer deste superPeer.
        /// </summary>
        /// <param name="superPeer"></param>
        /// <param name="subject"></param>
        /// <exception cref="RemotingException">Caso não consiga obter ligação com o SuperPeer.</exception>
        void SetSuperPeer(ISuperPeer superPeer, string subject);

        /// <summary>
        /// Serve para desligar este Peer dos sistema, notificando os Peers e SuperPeer com os quais este Peer esteja ligado.
        /// </summary>
        void Disconnect();
    }

    public interface ISuperPeer
    {
        string Url { get; set; }

        /// <summary>
        /// Método para adicionar um novo peer.
        /// </summary>
        /// <param name="subject"></param>
        /// <param name="peerName"></param>
        /// <param name="peer"></param>
        /// <exception cref="NotSupportedException">Se este Peer não for SuperPeer.</exception>
        void RegisterPeerFor(string subject, string peerName, IPeer peer);

        /// <summary>
        /// Método usado, pelos Peers que estiverem ligados a este SuperPeer, para indicar que o Peer vai sair do sistema.
        /// Este SuperPeer passa a não indicar este Peer nas próximas pesquisas GetPeersFor
        /// </summary>
        /// <param name="peerName"></param>
        void UnregisterPeer(string peerName);

        /// <summary>
        /// Método que devolve uma lista.
        /// </summary>
        /// <param name="subject"></param>
        /// <param name="superPeerName"></param>
        /// <param name="target"></param>
        /// <returns></returns>
        /// <returns>Retorna os Peers que o SuperPeer tem que conheçam o assunto indicado no parâmetro.</returns>
        IDictionary<string, IPeer> GetPeersFor(string subject, string superPeerName, IPeer target);

        /// <summary>
        /// Método para gerir a promoção de novos peers. Retorna o SuperPeer ao qual o Peer vai ficar ligado.
        /// </summary>
        /// <param name="peer"></param>
        /// <returns></returns>
        ISuperPeer PromoteToSuperPeer(IPeer peer);
    }

    public interface IArticle
    {
        string Title { get; set; }
        string[] Authors { get; set; }
        int YearOfPublication { get; set; }
        string Resume { get; set; }
    }
}
